package com.dhcc.bpm.modules.scf.service.impl;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dhcc.bpm.common.segmentId.LocalCacheIdGenerator;
import com.dhcc.bpm.modules.scf.dto.ScfDriverInfoDTO;
import com.dhcc.bpm.modules.scf.entity.ScfDriverInfo;
import com.dhcc.bpm.modules.scf.entity.ScfOperationLogInfo;
import com.dhcc.bpm.modules.scf.enumUtil.ScfOperationLogInfoEnum;
import com.dhcc.bpm.modules.scf.mapper.ScfDriverInfoMapper;
import com.dhcc.bpm.modules.scf.service.IScfDriverInfoService;
import com.dhcc.bpm.modules.scf.service.IScfFileAttachmentInfoService;
import com.dhcc.bpm.modules.scf.service.IScfOperationLogInfoService;
import com.dhcc.bpm.modules.scf.util.ExcelUtil;
import com.dhcc.bpm.modules.scf.util.OBSUtil;
import com.dhcc.bpm.modules.scf.vo.ScfDriverInfoVO.ScfGetDriverDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfDriverInfoVO.ScfGetDriverListVO;
import com.dhcc.bpm.modules.scf.vo.ScfFileAttachmentInfoVO.ScfFileAttachmentInfoVO;
import com.dhcc.bpm.modules.system.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;

@Service
@EnableScheduling
@Slf4j
public class ScfDriverInfoServiceImpl extends ServiceImpl<ScfDriverInfoMapper, ScfDriverInfo> implements IScfDriverInfoService {

    /**
     * 文件附件service接口
     */
    @Autowired
    private IScfFileAttachmentInfoService scfFileAttachmentInfoService;
    /**
     * id生成器
     */
    @Autowired
    private LocalCacheIdGenerator localCacheIdGenerator;
    /**
     * 操作日志service接口
     */
    @Autowired
    private IScfOperationLogInfoService scfOperationLogInfoService;
    /**
     * 用户服务service接口
     */
    @Autowired
    private IUserService userService;
    /**
     * obs对象存储工具类
     */
    @Autowired
    private OBSUtil obsUtil;

    /**
     * 查询司机列表
     *
     * @param page
     * @param scfDriverInfo
     * @return
     */
    @Override
    public IPage<ScfGetDriverListVO> selectScfDriverInfoPage(IPage<ScfGetDriverListVO> page, ScfDriverInfoDTO scfDriverInfo) {
        return page.setRecords(baseMapper.selectScfDriverInfoPage(page, scfDriverInfo));
    }

    /**
     * 查询司机详情
     *
     * @param scfDriverInfo
     * @return
     */
    @Override
    public ScfGetDriverDetailsVO getDetails(ScfDriverInfoDTO scfDriverInfo) {
        // 查询详细信息
        ScfGetDriverDetailsVO detail = baseMapper.getDetails(scfDriverInfo.getRowId());
        if (detail != null) {
            // 获取与文件附件表关联的id
            String rowId = detail.getRowId();
            // 查询关联的附件信息
            List<ScfFileAttachmentInfoVO> scfFileAttachmentInfoVOS = scfFileAttachmentInfoService.selectAllByAssociationId(rowId);
            // 如果查询到关联的附件信息
            if (scfFileAttachmentInfoVOS != null) {
                // 将附件信息存进dto里
                detail.setFileAttachmentInfoVOS(scfFileAttachmentInfoVOS);
            }
        }
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(detail.getRecorder()));
        detail.setRecorder(userService.selectUserNameByIds(ids).get(0));
        return detail;
    }

    /**
     * 新增司机
     *
     * @param scfDriverInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveDriver(ScfDriverInfoDTO scfDriverInfo) throws Exception {
        // 首先判断表中是否已有该司机记录-如果有则抛出一个异常信息：该司机已录入
        if (baseMapper.selectIsNullByLicense(scfDriverInfo.getLicense()) != null) {
            throw new Exception("司机:" + scfDriverInfo.getDriverName() + "已录入，请勿重复录入！");
        }
        // 初始驾驶证是否有效为（0：无效）
        String isvariale = "0";
        // 取出 驾驶证有效截止日
        String endDate = scfDriverInfo.getEndDate();
        // 转化为日期类型
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate date = LocalDate.parse(endDate, dateFormatter);
        // 获取当前的年月日
        LocalDate currentDate = LocalDate.now();
        // 判断截止日是否小于当前日期，如果小于则值为0：无效，大于或者等于当前日期则有效。
        if (!date.isBefore(currentDate)) {
            isvariale = "1";
        }
        // 生成日期
        String djDate = currentDate.toString();
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());
        // 获取当前年月日时分秒
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
        String recordTime = dateFormat.format(calendar.getTime());
        // 生成ROW_ID
        String rowId = "SJ" + localCacheIdGenerator.nextId() + formTime;
        // 开始补充对象字段start
        // 设置记录编号
        scfDriverInfo.setRowId(rowId);
        // 设置司机编号
        scfDriverInfo.setDriverNum(rowId);
        // 设置司机是否有效
        scfDriverInfo.setIsVariable(isvariale);
        // 设置登记日期
        scfDriverInfo.setRecordDate(djDate);
        // 设置登记时间
        scfDriverInfo.setRecordTime(formTime);
        // 补充对象字段结束end
        List<String> rowIds = scfDriverInfo.getRowIds();
        // 存储司机信息
        boolean isSave = save(scfDriverInfo);
        // 设置司机附件文件存放路径
        String path = "SJ" + "/" + rowId + "/";
        // 判断是否上传了文件，如果上传了则存储文件至obs及后续文件处理操作
        if (rowIds != null) {
            if (!rowIds.isEmpty()) {
                // 继续判断司机信息是否存储成功
                if (isSave) {
                    for (String fileRowId : rowIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId,null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将文件从临时文件夹复制到正式文件夹
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        // 同步更新文件附件表中正式文件夹的路径
                        scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                    }
                }
                scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
            }
        }
        // 记录操作日志
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfDriverInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.SUBJECT.getOperation());
        scfOperationLogInfo.setOperationFunction("司机信息维护");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.ADD.getOperation());
        scfOperationLogInfo.setOperationContent("新增一条司机信息，司机姓名：" + scfDriverInfo.getDriverName());
        scfOperationLogInfo.setRecordDate(recordTime);
        // 如果司机信息存储成功才可以存储操作日志记录
        if (isSave) {
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
        }
        return isSave;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int bachSaveDriver(List<ScfDriverInfo> scfDriverInfos, String operatorId) {
        List<ScfDriverInfo> scfDriverInfoList = new ArrayList<>();
        List<ScfOperationLogInfo> scfOperationLogInfoList = new ArrayList<>();
        for (ScfDriverInfo scfDriverInfo : scfDriverInfos) {
            // 设置登记人ID
            scfDriverInfo.setRecorder(operatorId);
            // 性别
            String sex = scfDriverInfo.getSex();
            if (sex != null) {
                switch (sex) {
                    case "男":
                        // 执行与 value1 匹配的代码块
                        scfDriverInfo.setSex("男");
                        break;
                    case "女":
                        // 执行与 value2 匹配的代码块
                        scfDriverInfo.setSex("女");
                        break;
                    // 可以有更多的 case 分支
                    default:
                        // 如果没有任何 case 匹配，则执行 default 代码块
                        break;
                }
            }
            // 将scfDriverInfoDTO传参给单个新增方法中。
            // 解析日期
            DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                    // 年份
                    .appendPattern("yyyy")
                    .optionalStart()
                    .appendLiteral('/')
                    .optionalEnd()
                    // 月份
                    .appendPattern("M")
                    .optionalStart()
                    .appendLiteral('/')
                    .optionalEnd()
                    // 日期
                    .appendPattern("d")
                    .toFormatter(Locale.ENGLISH);
            LocalDate date = LocalDate.parse(scfDriverInfo.getEndDate(), formatter);
            // 将日期格式化为目标格式
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String formattedDate = date.format(outputFormatter);
            scfDriverInfo.setEndDate(formattedDate);
            // 初始驾驶证是否有效为（0：无效）
            String isvariale = "0";
            // 获取当前的年月日
            LocalDate currentDate = LocalDate.now();
            // 判断截止日是否小于当前日期，如果小于则值为0：无效，大于或者等于当前日期则有效。
            if (!date.isBefore(currentDate)) {
                isvariale = "1";
            }
            // 生成年月日
            SimpleDateFormat dateTemp = new SimpleDateFormat("yyyyMMdd");
            String formatdate = dateTemp.format(new Date());
            // 生成时分秒
            SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
            String formTime = timeFormat.format(new Date());
            // 获取当前年月日时分秒
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
            String recordTime = dateFormat.format(calendar.getTime());
            // 生成ROW_ID
            String rowId = "SJ" + localCacheIdGenerator.nextId() + formTime;
            // 开始补充对象字段start
            // 设置记录编号
            scfDriverInfo.setRowId(rowId);
            // 设置司机编号
            scfDriverInfo.setDriverNum(rowId);
            // 设置司机是否有效
            scfDriverInfo.setIsVariable(isvariale);
            // 设置登记日期
            scfDriverInfo.setRecordDate(formatdate);
            // 设置登记时间
            scfDriverInfo.setRecordTime(formTime);
            // 补充对象字段结束end
            // 首先判断表中是否已有该司机记录
            if (baseMapper.selectIsNullByLicense(scfDriverInfo.getLicense()) == null) {
                scfDriverInfoList.add(scfDriverInfo);
                // 记录操作日志
                ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
                // 根据用户id查询用户名称，重新赋值登记人字段
                List<Long> ids = new ArrayList<>();
                ids.add(Long.valueOf(scfDriverInfo.getRecorder()));
                scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
                scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.SUBJECT.getOperation());
                scfOperationLogInfo.setOperationFunction("司机信息维护");
                scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.ADD.getOperation());
                scfOperationLogInfo.setOperationContent("新增一条司机信息，司机姓名：" + scfDriverInfo.getDriverName());
                scfOperationLogInfo.setRecordDate(recordTime);
                scfOperationLogInfoList.add(scfOperationLogInfo);
            }
        }
        boolean saveBatch = saveBatch(scfDriverInfoList);
        if (saveBatch) {
            scfOperationLogInfoService.bachSaveOperationLogInfo(scfOperationLogInfoList);
        }
        return scfDriverInfoList.size();
    }

    /**
     * 司机更新
     *
     * @param scfDriverInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDrtver(ScfDriverInfoDTO scfDriverInfo) {
        // 生成年月日
        SimpleDateFormat dateNow = new SimpleDateFormat("yyyyMMdd");
        String formatdate = dateNow.format(new Date());
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());
        // 获取当前年月日时分秒
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
        String recordTime = dateFormat.format(calendar.getTime());
        // 初始驾驶证是否有效为（0：无效）
        String isvariale = "0";
        // 取出 驾驶证有效截止日
        String endDate = scfDriverInfo.getEndDate();
        // 转化为日期类型
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate date = LocalDate.parse(endDate, dateFormatter);
        // 获取当前的年月日
        LocalDate currentDate = LocalDate.now();
        // 判断截止日是否小于当前日期，如果小于则值为0：无效，大于或者等于当前日期则有效。
        if (!date.isBefore(currentDate)) {
            isvariale = "1";
        }
        // 设置新的记录有效状态
        scfDriverInfo.setIsVariable(isvariale);
        boolean update = updateById(scfDriverInfo);
        // 获取当前司机信息记录的主键rowId
        String rowId = scfDriverInfo.getRowId();
        // 获取更新司机信息上传的文件附件
        List<String> rowIds = scfDriverInfo.getRowIds();
        // 设置司机附件文件存放路径
        String path = "SJ" + "/" + rowId + "/";
        // 如果可以拿到当前司机的记录的主键rowId则继续
        if (update) {
            if (rowId != null) {
                // 如果上传了新的文件则继续
                if (!rowIds.isEmpty()) {
                    // 取消旧文件与记录关联
                    scfFileAttachmentInfoService.updataFiledNull(rowId);
                    // 给上传的新文件添加关联编号
                    scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
                    for (String fileRowId : rowIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId,null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将文件从临时文件夹复制到正式文件夹
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        // 更新文件附件记录
                        scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                    }
                }
            }
        }
        // 记录操作日志
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfDriverInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.SUBJECT.getOperation());
        scfOperationLogInfo.setOperationFunction("司机信息维护");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.UPDATE.getOperation());
        scfOperationLogInfo.setOperationContent("更新一条司机信息，司机姓名：" + scfDriverInfo.getDriverName());
        scfOperationLogInfo.setRecordDate(recordTime);
        // 司机信息更新成功后才可继续存储操作日志记录
        if (update) {
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
        }
        return update;
    }

    /**
     * 批量导入司机信息记录
     *
     * @param operatorId
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public List<ScfDriverInfo> batchSaveScfDriverInfo(String operatorId, MultipartFile file) throws IOException {
        // 获取文件的Base64编码
        byte[] fileBytes = file.getBytes();
        // 解析excel文件获取数据集合
        List<ScfDriverInfo> scfDriverInfos = ExcelUtil.readExcel(fileBytes, ScfDriverInfo.class, "司机信息", 3);
        log.info("数据集合为：{}", scfDriverInfos);
        return scfDriverInfos;
    }


    /**
     * 定时更新司机驾驶证状态
     */
    @Scheduled(cron = "0 0 0 * * ?")
    // @Scheduled(cron = "0/5 * * * * ?")
    public void updateIsVariable() {
        Date currentDate = new Date();
        // 获取当前时间
        baseMapper.updateIsVariable(currentDate);
        log.info("定时更新司机驾驶证状态任务已执行！");
    }


    @Override
    public Boolean deleteByIds(String[] ids) {
        return this.baseMapper.deleteByIds(ids);
    }
}
